package com.i3q360.layui.common.base;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;

import com.i3q360.layui.common.util.PageInfo;
import com.i3q360.layui.modular.system.entity.SysPermission;

public abstract class BaseService <T,D extends JpaRepository<T,Integer>>{
	
	private static final String LIMIT = "limit";
	private static final String OFFSET = "offset";
	private static final String ORDER = "order";
	private static final String SORT = "sort";
	@Autowired
	protected D dao;
	Class<T> entityClass;
	protected String simpleName;
	protected String countSql;
	protected String selectSql;

	
	public BaseService(){
		Type genType = getClass().getGenericSuperclass();  
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); 
		entityClass =  (Class)params[0];
		simpleName = entityClass.getSimpleName();
		countSql = "select count(*) from "+ simpleName +" a where 1=1 ";
		selectSql = "from "+ simpleName + " where 1=1 ";
	}
	
    @PersistenceContext
    EntityManager entityManager;
    
    
    
    public PageInfo<T> queryPage(Map<String,String> params ){
    	
    	Map<String,Object> parameters = new HashMap<>();
    	String whereSql = whereSql(params,parameters);
    	
    	int limit,offset;
		limit = Integer.parseInt(params.get(LIMIT));
		offset = Integer.parseInt(params.get(OFFSET));
		String order = params.get(ORDER);
		String sort = params.get(SORT);
    	long count = queryCount(countSql + whereSql,parameters);
    	List<T> list = queryPage(selectSql , whereSql , orderSql(sort,order),parameters,offset,limit);
    	PageInfo<T> page = new PageInfo<T>(count,list);
    	return page;
    	
    }	
    
    
    //总数
    private Long queryCount(String countSql,Map<String,Object> params){
    	
    	Query countQuery = this.entityManager.createQuery(countSql,Long.class);
    	this.setParameters(countQuery, params);
    	return (Long)countQuery.getSingleResult(); 
    }
    
    //sort前端排序对象
    @SuppressWarnings("unchecked")
	private List<T> queryPage(String selectSql,String whereSql,String orderSql,Map<String,Object> params,int offset,int limit){
    	
    	selectSql+=whereSql+=orderSql;
    	Query query = this.entityManager.createQuery(selectSql,entityClass);
    	
    	this.setParameters(query, params);
    	query.setFirstResult(offset);
    	query.setMaxResults(limit);
    	return query.getResultList();
    }

    
    
    public List<T> queryList(Map<String,Object> params){
    	
    	Map<String,Object> parameters = new HashMap<String,Object>();
    	String selectQuerySql = selectSql + whereSql(params,parameters);
    	Query query = this.entityManager.createQuery(selectQuerySql,entityClass);
    	this.setParameters(query, parameters);
    	return query.getResultList();
    }
    
    public List<T> queryList(String key,Object value){
    	Map<String,Object> parameters = new HashMap<String,Object>();
    	String selectQuerySql = selectSql + whereSql(key,value,parameters);
    	Query query = this.entityManager.createQuery(selectQuerySql,entityClass);
    	this.setParameters(query, parameters);
    	return query.getResultList();
    }
    
    public List<T> queryList(Sort sort){
    	return dao.findAll(sort);
    }
    
    
    /**
     * 给hql参数设置值
     * @param query 查询
     * @param params 参数
     */
    private void setParameters(Query query,Map<String,Object> params){
        for(Map.Entry<String,Object> entry:params.entrySet()){
            query.setParameter(entry.getKey(),entry.getValue());
        }
    }
   
    
    protected String whereSql(Map<String,?> map,Map<String,Object> parameters ){
    	
    	StringBuilder builder = new StringBuilder();
    	String where = null;
    	for(Entry<String,?> entry : map.entrySet()){
    		if( entry.getValue()!=null && String.valueOf(entry.getValue())!="" ){
      			 where = whereSql(entry.getKey(),entry.getValue(),parameters);
      			 where = where!=null ? where : "";
      			 builder.append(where);
   	   		}	
    	}

    	return builder.toString();
    }
    
    protected String orderSql(String sort,String order){
    	if(StringUtils.isNotBlank(sort)){
    		return " order by " + sort +" " + order;
    	}else
    		return orderSql();
    }
    
    
    public abstract String whereSql(String paramKey,Object paramValue,Map<String,Object> parameters);
    public abstract String orderSql();
    
    
    public T queryById(Integer id){
    	return dao.getOne(id);
    }
    
    @Transactional
    public T save(T t){
    	return dao.save(t);
    }
    
    @Transactional
    public void delete(T t){
    	dao.delete(t);
    }
    
    
    
}
